In this tutorial we will use Brython, an implementation of Python written in javascript and Python, to access the OpenLayers javascript library and to manage the data to be used in the maps. To integrate Brython in the IPython notebook we are using an extension for the notebook called brythonmagic that provides a new magic cell, **%%brython**
, that allow us to write and execute Brython code in the notebook.
As stated before, we will use Brython, and brythonmagic so first of all we need to load the extension and the Brython library.
So, let's load the extension:
In [ ]:
!pip install brythonmagic
In [1]:
%load_ext brythonmagic
And the brython js lib:
In [2]:
from brythonmagic import load_brython_dev
load_brython_dev()
[It is highly recommended that, at least, you read the brythonmagic docs to understand what it does. It is also recommended to have a quick look at the Brython docs].
In order to load javascript libraries in a safety way you should try to use https instead of http when possible (read more here). If you don't trust the source and/or the source cannot be loaded using https then you could download the javascript library and load it from a local location.
In the following tutorial I will try to follow several conventions to try to make it more readable.
Code in cells that are not code cells:
# This is a block of code
print("Hello world!")
**this is a piece of Python/Brython code inline with the text**
**this is a piece of javascript code inline with the text**
OpenLayers is an open source, client side JavaScript library for making interactive web maps, viewable in nearly any modern web browser. Since it is a client side library, it requires no special server side software or settings — you can use it without even downloading anything!
The website for OpenLayers is located at http://openlayers.org/. To begin, we need to download a copy of OpenLayers (or, we can directly link to the library — this is what we will do in the present tutorial). You can download the compressed library as either a .tar.gz or .zip, but both contain the same files.
So, before continuing let's load the OpenLayers library.
In [3]:
from brythonmagic import load_js_lib
load_js_lib("https://cdnjs.cloudflare.com/ajax/libs/openlayers/2.11/OpenLayers.js")
Right now OpenLayers3 (ol3) is in active development and OpenLayers2 is in maintenance mode. The main idea of ol3 is to simplify the use of the library. From their web page:
We've begun the development effort to make the next major version of OpenLayers a reality. OpenLayers 3 is a comprehensive rewrite of the library, targeting the latest in HTML5 and CSS3 features. The library will continue to have broad support for projections, standard protocols, and editing functionality from OpenLayers 2.x. The new version of the library will focus on performance improvements, lighter builds, prettier visual components, an improved API, and more. Some of the major highlights are:
In this tutorial we will be using OpenLayers2.
As this is just an introductory tutorial we will be working mainly with the following classes:
OpenLayers.Map
: an instance of this class will be the main piece of the mapping app. Their methods will be called when we want to zoom to areas, keep track of the layers, play with events,...OpenLayers.Layer
: The info/data/... of our map will be an instance of OpenLayers.Layer
or one of its subclasses. Each map will need, at least, a layer, the base layer.First we create some simple HTML code. This HTML code will contain our map. We will not use complicated HTML code during the tutorial to keep it simple and to be focused in 'How to create interactive maps in the browser with Python'. There is a lot of amazing resources to learn about HTML and CSS.
In [4]:
html="""<div id="map_ex1" style="width: 500px; height: 300px;"></div>"""
Now the interesting part. To make OpenLayers(2) available to Brython we need to 'load' the OpenLayers object/namespace to Brython using **OpenLayers = window.OpenLayers**
. We will use the **new**
method injected by Brython to the Javascript object that would behave similarly as if we were using Javascript constructors, (ie functions used with the Javascript keyword **new**
).
The code is as follows:
In [5]:
%%brython -h html -p
from browser import window
OpenLayers = window.OpenLayers
mymap = OpenLayers.Map.new('map_ex1')
layer1 = OpenLayers.Layer.OSM.new()
mymap.addLayer(layer1)
mymap.zoomToMaxExtent()
Pretty simple!!
Ok, let's dissect the code in the Brython cell above.
**%%brython -h html -p**
:
-h
to use the HTML code defined in the html
variable and -p
to print the final HTML code generated below the generated map. In this example, the generated code should be something like the following:<script id="422523" type="text/python">
from browser import window
OpenLayers = window.OpenLayers
mymap = OpenLayers.Map.new('map_ex1')
layer1 = OpenLayers.Layer.OSM.new()
mymap.addLayer(layer1)
mymap.zoomToMaxExtent()
</script>
<div id="brython_container_422523"><div id="map_ex1" style="width: 500px; height: 300px;"></div></div>
<script type="text/javascript">brython({debug:1, static_stdlib_import: false, ipy_id: ["422523"]});</script>
the -p
option only provides information and it isn't required to run the Brython code cell.
**from browser import window**
**browser**
is a special module available only in Brython that allows to interact with the browser, the document, the window,...**OpenLayers = window.OpenLayers**
**OpenLayers**
object/namespace (JS lib) accesible to the Brython namespace.**mymap = OpenLayers.Map.new('map_ex1')**
**var mymap = new OpenLayers.Map('map_ex1');**
**layer1 = OpenLayers.Layer.OSM.new()**
**var layer1 = new OpenLayers.Layer.OSM();**
**mymap.addLayer(layer1)**
**mymap.addLayers([layer1, layer2,...])**
. We can add several layers once using the method addLayers
or we can add several layers using several times the method addLayer
. The following:map.addLayer(layer1)
map.addLayer(layer2)
would be equivalent to:
map.addLayers([layer1, layer2])
**mymap.zoomToMaxExtent()**
As commented before, an instance of OpenLayers.Map
will be one of the main parts of our mapping application. It accepts the following inputs:
You can set and/or change the options value at any moment using the **OpenLayers.Map**
methods. Some of these options will not work with Brython (I have to analyse why) and it is better to use methods to modify a default parameter.
First we define the HTML code where the map will be rendered (div element with id="map_ex2"
) and another div (div element with id="data"
) where we will print some data of the actual map. The information from the map is included in the function **get_data**
.
**[NEW CODE]** In the example below there is some Brython specific code like the operator <=
. This operator is a little bit controversial. You can read the last question in the FAQ of the Brython docs to learn more. If you don't like this operator or you think it is confusing you can use an alternative syntax. You can change:
element <= element_child
with
element.appendChild(element_child)
In [6]:
html="""<div style="container: relative">
<div id="map_ex2" class="ex2"></div>
<div id="data" class="ex2"></div>
</div>
<style>
#data {background-color: cyan;}
.ex2 {width: 500px;
height: 300px;
container: relative;
float: left;
padding-left: 15px;}
</style>"""
In [7]:
%%brython -h html
from browser import document, html
from browser import window
OpenLayers = window.OpenLayers
layer1 = OpenLayers.Layer.WMS.new("Base layer (default)",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{"layers": "basic"},
{"wrapDateLine": True})
mymap = OpenLayers.Map.new()
mymap.addLayer(layer1)
# Set the center
location = OpenLayers.LonLat.new(0, 40)
mymap.setCenter(location, 5)
# We use render method instead of defining the container in the map instance
mymap.render('map_ex2')
# Now let's extract some info of the actual map and show it in a div container below:
my_div = document["data"]
my_div <= html.BUTTON('grab the info!', Id = "button_ex2", Class = "btn")
my_div <= html.DIV(Id = "container_data")
def get_data(ev):
data_div = document["container_data"]
data_div.html = ""
print('entro')
data_div <= html.P("lon center = " + str(mymap.getCenter().lon))
data_div <= html.P("lat center = " + str(mymap.getCenter().lat))
data_div <= html.P("Projection = " + str(mymap.getProjection()))
data_div <= html.P("Bounds (left) = " + str(mymap.getExtent().left))
data_div <= html.P("Bounds (right) = " + str(mymap.getExtent().right))
data_div <= html.P("Bounds (bottom) = " + str(mymap.getExtent().bottom))
data_div <= html.P("Bounds (top) = " + str(mymap.getExtent().top))
#...
document["button_ex2"].bind("click", get_data)
**[NEW CODE]** In the example above we have used **OpenLayers.LonLat.new(0, 40)**
(**new OpenLayers.LonLat(0, 40)**
in javascript). It is an object that represents a pair of longitude and latitude coordinates.
A layer is basically a way to show multiple levels of information and each level is independent of each other. As we saw in the previous example, when we want to actually create a layer, we create an object from an OpenLayers Layer class.
OpenLayers has many different Layer classes, each allowing you to connect to a different type of map server 'back end.' For example, if you want to connect to a WMS map server, you would use the Layer.WMS
class, and if you want to use Google Maps you'd use the Layer.Google
class. Each layer object is independent of other layer objects, so doing things to one layer won't necessarily affect the other.
Whatever the purpose of your web map application is, you will need at least one layer to have a usable map, at least one Base layer. All other layers that 'sit above' the base layer are called Overlay layers. These are the two 'types' of layers in OpenLayers.
A base layer is at the very bottom of the layer list, and all other layers are on top of it. The base layer is always visible and determines some map properties such as projection and zoom levels.
The order of the other layers can change, but the base layer is always below the overlay layers. By default, the first layer that you add to your map acts as the base layer. You can, however, change the property of any layer on your map to act as the base layer (by setting the isBaseLayer
property to True
). As said before, a map can have more than one base layer but only one of them can be active at a time. When one base layer is turned on, all the other base layers are turned off. In addition, if you add more than one flagged base layer to the map, the first base layer added will be used as the active base layer of the map.
First, we define the container where the map will be included:
In [8]:
html="""<div id="map_ex3" style="width: 700px; height: 300px;"></div>"""
And now, we define two layers and both of them will be treated as base layers but the first one defined would be the base layer as we do not define explicitly which one should be used. The default layer will be a basic map while the other base layer will be the blue marble imagery. We will add a control to choose the base layer to be shown (later we will talk more about predefined controls in OpenLayers).
In [9]:
%%brython -h html
from browser import window
OpenLayers = window.OpenLayers
mymap = OpenLayers.Map.new('map_ex3')
layer1 = OpenLayers.Layer.WMS.new("Base layer (default)",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{"layers": "basic"},
{"wrapDateLine": True})
layer2 = OpenLayers.Layer.WMS.new("Other base layer, Blue Marble",
"http://maps.opengeo.org/geowebcache/service/wms",
{"layers":"bluemarble"},
{"wrapDateLine": True})
mymap.addLayers([layer1, layer2])
# We will define this later.
control = OpenLayers.Control.LayerSwitcher.new()
mymap.addControl(control)
location = OpenLayers.LonLat.new(20, 50)
mymap.setCenter(location, 3)
**[NEW CODE]** In the definition of the layers in the Brython code cell above we included the option **wrapDateLine**
and was set to **True**
. There might be situations where you do not want your map ends at -180 or +180 longitude degrees as you are working in that area and need a continuous map. This option helps you to achieve this.
OpenLayers.Layer.WMS
layer used in the example above.In the previous example we have seen that we used several arguments in the definition of **layer1**
or **layer2**
. See, for instance, **layer1**
definition below:
layer1 = OpenLayers.Layer.WMS.new("Base layer (default)",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{"layers": "basic"},
{"wrapDateLine": True})
The arguments used are as follows:
Name
, the first parameter, **"Base layer (default)"**
, defines the name of the layer.Url
, the second parameter, **"http://vmap0.tiles.osgeo.org/wms/vmap0"**
in this case, is the url of the map server.Params
, the third parameter, **{"layers": "basic"}**
, is a Python dictionary (javascript anonymous object). This parameter specifies server side settings that affect the map image, which the WMS server returns. The key:value pairs you pass in here will be appended (more or less) to the URL that OpenLayers generates when it makes requests to the map server. An example of one of the urls generated to get a tile in this example is the following:
The params parameter depends on the map server and it is out of the scope of this tutorial to explain all the possibilities.
Options
, the fourth parameter, **{"wrapDateLine": True}**
in this case, is a Python dictionary (javascript anonymous object). The options dictionary/object contains properties for the client side OpenLayers Layer object. These are the settings for the layer object itself, so all Layer classes have this parameter.Overlay layers (non base layers), however, do not behave the way the base layers work, turning on or off overlay layers will not affect other overlay layers. Base layers are similar to radio buttons, only one can be active at a time. Overlay layers are similar to check boxes, you can have as many on or off as you'd like. Any layer that is not a base layer is called an overlay layer. Like we talked about, the order that you add layers to your map is important. Every time you add a layer to the map, it is placed above the previous one, take this into account!!!!
As usual, first the HTML code where the map will be rendered.
In [10]:
html = """<div id="map_ex4" style="width: 700px; height: 300px;"></div>"""
And now the script code. In this case we will use the **OpenLayers.Layer.Image**
of the **OpenLayers.Layer**
class. More about this subclass here.
In [12]:
%%brython -h html
from browser import window
OpenLayers = window.OpenLayers
mymap = OpenLayers.Map.new('map_ex4')
layer1 = OpenLayers.Layer.Image.new('Python',
'https://farm6.staticflickr.com/5257/5513104816_d73f41eddb_o.jpg',
OpenLayers.Bounds.new(-180,-112.5,180,112.5),
OpenLayers.Size.new(3264,2448),
{"numZoomLevels": 7,
"maxResolution":.750})
layer2 = OpenLayers.Layer.Image.new('My Python',
'https://www.python.org/static/community_logos/python-logo-master-v3-TM.png',
OpenLayers.Bounds.new(-100,-45,100,45),
OpenLayers.Size.new(601,203),
{"numZoomLevels": 7,
"maxResolution":.750,
"isBaseLayer": False,
"opacity": 0.25})
mymap.addLayers([layer1, layer2])
# We will define this later.
control = OpenLayers.Control.LayerSwitcher.new()
mymap.addControl(control)
location = OpenLayers.LonLat.new(0, 0)
mymap.setCenter(location, 2)
In the example above we have used one image as a base layer and a new one as an overlay layer. Some arguments used are the same defined above, name, url
and options
.
**[NEW CODE]** We have used two new parameters,
extent
, i.e. the following in the script **OpenLayers.Bounds.new(-100,-45,100,45)**
(equivalent javascript code would be **new OpenLayers.Bounds(-100,-45,100,45)**
). This parameter establish the bounding box for the image, and size
, i.e. the following in the script **OpenLayers.Size.new(601, 203)**
(equivalent javascript code would be **new OpenLayers.Size(601, 203)**
). This parameter is the width and height of the image.In the options parameter we have included **"opacity": 0.25**
that tells the layer to have an opacity of 0.25 (values between 0 to make the layer transparent or 1 to be opaque)
It is out of the scope of this tutorial talk about all the available subclasses of the **OpenLayers.Layer**
class but at least you should know there are other available as Google
, Bing
, Yahoo
, Mapguide
, Vector
,...
Until now we have seen raster layers (WMS, Image, Google, Bing,
...) The Vector
layer will be explained below as it is quite usual and helpful and it is a way to data interesting data in a geographical context.
First of all, what is a vector in this context? A vector uses geometrical shapes based on math equations to form an image. As main characteristics, the quality is preserved when you zoom in and vector graphics are not constrained to a grid, so they preserve shape at all scales.
The vector data must be rendered to be seen. OpenLayers supports three ways to render the vector layer: SVG (<svg>
tag in HTML5), Canvas (<canvas>
tag in HTML5) and VML (special case for dirty browsers that don't follow the standards like IE).
When we are working with vector layers we make use of other classes. The Vector class makes use of the Feature class to show objects on the layer. And in turn for the Feature class to work, it needs to use the Geometry class to create geometry objects. Therefore, the actual vector objects in your vector layers are Feature objects which are composed of Geometry objects. It seems more complicated than using raster layers so let's see an example before to see a vector layer working.
The easiest way to better understand what is a Vector layer, what is a feature, what is a geometry, etc, is to play a little bit with it and later we will dive deeper on the concepts. First the HTML code:
In [13]:
html = """<div id="map_ex5" style="width: 700px; height: 400px;"></div>"""
And now we will draw a map using OSM as the base layer and an empty vector layer. We also add a new control - more on OpenLayers built-in controls later - to draw some elements in the vector layer. Play a little bit with it, located on the upper rigt side of your map, and later we will continue:
In [15]:
%%brython -h html
from browser import window
OpenLayers = window.OpenLayers
mymap = OpenLayers.Map.new('map_ex5')
layer1 = OpenLayers.Layer.OSM.new()
layer_vector = OpenLayers.Layer.Vector.new('My vector layer')
mymap.addLayers([layer1, layer_vector])
# We will define this later.
control_vector = OpenLayers.Control.EditingToolbar.new(layer_vector)
mymap.addControl(control_vector)
location = OpenLayers.LonLat.new(0, 40)
mymap.setCenter(location, 2)
**[NEW CODE]** We have used a new built-in control and a new layer type,
**control_vector = OpenLayers.Control.EditingToolbar.new(layer_vector)**
(equivalent javascript code would be **var control_vector = new OpenLayers.Control.EditingToolbar(layer_vector)**
). This control allow us to insert some information attached to the vector layer defined (**layer_vector**
in the example above). More on controls later.**layer_vector = OpenLayers.Layer.Vector.new('My vector layer')**
(equivalent javascript code would be **var layer_vector = new OpenLayers.Layer.Vector('My vector layer')**
). This is an OpenLayers.Layer
subclass to work with vector information.The OpenLayers.Layer.Vector
subclass has many methods to manipulate data and to add interactivity to the features, the layer and the map itself. Let's work with some of them. In the following paragraphs we will try to explain how to add some features programmatically using some methods of the vector layer class.
As I stated before, The Vector class makes use of the Feature class to show objects on the layer. And in turn for the Feature class to work, it needs to use the Geometry class to create geometry objects. The Feature.Vector
class uses the Geometry class to store geometry information (i.e., it stores geographic information) about a feature.
If you have some knowledge of GIS you will have worked with points, polygons, linear rings, lines or paths,... All these 'things' are usually called geometries in the GIS world. OpenLayers has several subclasses that inherit from the OpenLayers.Geometry
class to define geometries. For example, to create a Point you can use the following javascript code, **new OpenLayers.Geometry.Point(20, 40);**
, i.e., a point at the coordinate 20, 40.
The Feature class is what the Vector class uses to actually show Geometry objects on the map. The base Feature class is composed of two things—Geometry objects (as you've seen), and attributes. The attributes contain data associated with the feature. There is only one subclass we'll be making use of — the OpenLayers.Feature.Vector
class. Like its parent Feature class, it is composed of a Geometry object and contains an attributes property. In addition, there is a style property which controls what the feature looks like. The feature object will accept a geometry object, some attributes related with the object (a Python dictionary/a javascript anonymous object) and a style object.
We'll continue with our 'learn by doing' strategy so here is a new example to practice with geometries, features and vector layers.
In [16]:
html = """<div id="map_ex6" style="width: 700px; height: 300px;"></div>"""
We will plot data from the Hurricane Vince, occurred in 2005 around the Iberian Peninsula (Portugal and Spain).
In [18]:
%%brython -h html
from browser import window
OpenLayers = window.OpenLayers
mymap = OpenLayers.Map.new('map_ex6')
layer1 = OpenLayers.Layer.WMS.new("Base layer",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{"layers": "basic"})
layer_vector_points = OpenLayers.Layer.Vector.new('Points')
# Hurricane Vince data
# http://www.nhc.noaa.gov/pdf/TCR-AL242005_Vince.pdf
lats = [32.9, 33.0, 33.1, 33.2, 33.4, 33.8, 34.1, 34.3,
34.5, 34.7, 35.4, 36.1, 36.7, 37.7, 37.2]
lons = [-20.6, -20.3, -20.1, -20.0, -19.6, -19.3, -18.9,
-18.3, -17.2, -15.3, -12.8, -10.5, -8.3, -6.0, -7.1]
# Points of the Vince locations each 6 hours
feats = []
for lon, lat in zip(lons, lats):
point = OpenLayers.Geometry.Point.new(lon, lat)
feat = OpenLayers.Feature.Vector.new(point)
feats.append(feat)
layer_vector_points.addFeatures(feats)
#mymap.addLayer(layer1)
mymap.addLayers([layer1,layer_vector_points])
# We will define this later.
control = OpenLayers.Control.LayerSwitcher.new()
mymap.addControl(control)
center = OpenLayers.LonLat.new(-10, 35)
mymap.setCenter(center, 4)
**[NEW CODE]** We have used a new built-in control and a new layer type,
**point = OpenLayers.Geometry.Point.new(lon, lat)**
(equivalent javascript code would be **var point = new OpenLayers.Geometry.Point(lon, lat)**
). This control allow us to create point geometries at desired locations.**feat = OpenLayers.Feature.Vector.new(point)**
(equivalent javascript code would be **var feat = new OpenLayers.Feature.Vector(point)**
). It allows us to include geometry information in the vector layer.**layer_vector_points.addFeatures(feats)**
(code is similar in javascript). Add the feature to the layer.Without controls, our map will not be interactive so, in essence, controls allow us to interact with the map. There are several built-in controls provided by the OpenLayers library: controls to zoom in and out, to play with layers, to show a scale bar, to measure distances,... We already have seen some of this controls.
The OpenLayers.Control
class is the base class for all the controls and contains the
common properties and methods that a control can have. Some controls are added automatically to the map. In the previous examples we saw that controls to zoom in and zoom out are available by default, we saw that we can use the mouse to move the map,...
Let's see a new map including some non-default controls. In this case we will add a scale line and a control to display the position of the mouse. First the html to be used in the example:
In [19]:
html = """<div id="map_ex7" style="width: 700px; height: 300px;"></div>"""
And now the Brython code:
In [20]:
%%brython -h html
from browser import window
OpenLayers = window.OpenLayers
mymap = OpenLayers.Map.new('map_ex7')
layer1 = OpenLayers.Layer.WMS.new("Base layer",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{"layers": "basic"})
mymap.addLayer(layer1)
# Scale bar control.
control_scale = OpenLayers.Control.ScaleLine.new()
# Mouse position control.
control_mouse_pos = OpenLayers.Control.MousePosition.new()
mymap.addControls([control_scale, control_mouse_pos])
center = OpenLayers.LonLat.new(-10, 35)
mymap.setCenter(center, 4)
**[NEW CODE]** We have used two new built-in controls,
**control = OpenLayers.Control.ScaleLine.new()**
(equivalent javascript code would be **var control = new OpenLayers.Control.ScaleLine()**
). This control will display a scale bar. If you zoom in or zoom out you will see how the scale bar is updated.**control = OpenLayers.Control.MousePosition.new()**
(equivalent javascript code would be **var control = new OpenLayers.Control.MousePosition()**
). It will display the coordinates of the mouse location over the map.Remember that we saw other non-default controls in previous examples:
OpenLayers.Control.LayerSwitcher
. It adds a control to play with layers.OpenLayers.Control.EditingToolbar(
layer)
. It add controls to create and edit vector features.The OpenLayers.Control
class in the base class used by the built-in controls that we have been using in the previous examples. Some methods available on each subclass are destroy()
, moveTo(location)
, activate()
, deactivate()
and draw()
. If you are very clever you will guess the actions obtained using these methods, if you are like me you could visit the official docs linked above :-P
We will see some of the subclasses of the OpenLayers.Control
class:
OpenLayers.Control.Permalink
. This control will add a link (Permalink) with the current longitude, latitude, zoom and visible layers of the map. It will appear in the bottom right side in the following example.OpenLayers.Control.Attribution
. It show some information of the actual map (or whatever you want). It is added using the attribution property in the layer you want to provide information. It will appear in the bottom right side in the following example.OpenLayers.Control.KeyboardDefaults
. If we set this control we can control our map by pressing the arrow keys, plus/minus keys, or home keys, the map will be moved or zoomed. There is one relevant property we should take a look at.OpenLayers.Control.Graticule
. It adds a grid to the map.OpenLayers.Control.Navigation
. This control is added by default to the map and it provides the ability to interact with the map using the mouse.OpenLayers.Control.NavigationHistory
. Yes, you guessed it. History of the navigation. This is not shown in the example below.OpenLayers.Control.NavToolbar
, OpenLayers.Control.PanZoom
, OpenLayers.Control.PanZoomBar
, OpenLayers.Control.ZoomPanel
and OpenLayers.Control.PanPanel
. These controls offer the same than that we can get using the mouse, controls to pan and zoom and displace around the map. They are located in the top left side of the map. In the example below we use OpenLayers.Control.PanZoomBar
.OpenLayers.Control.Scale
. It adds ratio scale information on the right bottom side of the map.OpenLayers.Control.OverviewMap
. It adds a panel to see the displayed map, current position map, in a more general map. It is a toggle-able window located on the right bottom side of the map.
In [21]:
html = """<div id="map_ex8" style="width: 700px; height: 500px;"></div>"""
In [22]:
%%brython -h html
from browser import window
OpenLayers = window.OpenLayers
mymap = OpenLayers.Map.new('map_ex8',
# the following line will clean the default controls
{"controls": []})
layer1 = OpenLayers.Layer.WMS.new("Base layer",
"http://vmap0.tiles.osgeo.org/wms/vmap0",
{"layers": "basic"},
# The following line is used to add the attribution
{"attribution": "Python cool maps factory"})
mymap.addLayer(layer1)
# Permalink control.
control_perma = OpenLayers.Control.Permalink.new()
# Attribution control (default control).
# As we have removed all default controls, see the map instance,
# we should explicitly use this.
control_attrib = OpenLayers.Control.Attribution.new()
# Graticule control.
control_grat = OpenLayers.Control.Graticule.new()
# Toolbar to move up, down, left and right, zoom and pan.
control_toolbar = OpenLayers.Control.PanZoomBar.new()
# Position of the mouse in the map coordinates.
control_mouse_pos = OpenLayers.Control.MousePosition.new()
# Default keyboard controls.
control_keyb = OpenLayers.Control.KeyboardDefaults.new()
# Add scale information.
control_scale = OpenLayers.Control.Scale.new()
# Navigation control. This control is added by default.
# As we have removed all default controls, see the map instance,
# we should explicitly use this.
control_navi = OpenLayers.Control.Navigation.new()
# OverviewMap control.
control_overview = OpenLayers.Control.OverviewMap.new()
mymap.addControls([control_perma, control_attrib, control_grat,
control_toolbar, control_mouse_pos,
control_keyb, control_scale,
control_navi, control_overview])
center = OpenLayers.LonLat.new(-10, 35)
mymap.setCenter(center, 4)
We could also create custom controls using OpenLayers (this is out of the scope of the present tutorial) or using vanilla Brython/javascript (see example 2 in this tutorial to see a simple case).
In the present tutorial we have seen very briefly how to create maps, how to use raster and vector layers, how to add controls, how to create custom controls,..., using Python/Brython instead of Javascript. Maybe some OpenLayers stuff will not work by default with Brython (if you find an issue, please, let me know) but most of this javascript library is accesible by Brython using a more pythonic syntax.
If you want to learn more about OpenLayers you have excellent books here.
If you have suggestions, want to provide feedback, report bugs, ask questions,..., you can open an issue here.